package com.dongwu.common.service.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.transaction.annotation.Transactional;

import com.dongwu.common.dao.BaseDao;
import com.dongwu.common.dao.DynamicSpecifications;
import com.dongwu.common.dao.SearchFilter;
import com.dongwu.common.entity.BaseEntity;
import com.dongwu.common.service.IBaseService;

public class BaseServiceImpl<T extends BaseEntity, ID extends Serializable> implements IBaseService<T, ID> {

	protected  Logger log = LoggerFactory.getLogger(this.getClass());

	@Autowired
	protected BaseDao<T, ID> baseRepository;
	@PersistenceContext
	 protected EntityManager em;

	Class<T> entityClass = null;
	
	public BaseServiceImpl() {
		Type t = getClass().getGenericSuperclass();
		if (t instanceof ParameterizedType) {
			Type[] p = ((ParameterizedType) t).getActualTypeArguments();
			entityClass = (Class<T>) p[0];
		}
	}
  
	@Transactional(readOnly = true)
	public List<T> findAll() {
		return baseRepository.findAll();
	}

	@Transactional(readOnly = true)
	public Page<T> findPage(PageRequest pageRequest,
			Map<String, Object> searchParams) {
		Map<String, SearchFilter> filters = SearchFilter.parse(searchParams);
		Specification<T> spec = DynamicSpecifications.bySearchFilter(filters.values(), entityClass);
		
		return baseRepository.findAll(spec, pageRequest);
	}
	@Override
	public Iterable<T> findList(Map<String, Object> searchParams) {
		Map<String, SearchFilter> filters = SearchFilter.parse(searchParams);
		Specification<T> spec = DynamicSpecifications.bySearchFilter(filters.values(), entityClass);
		
		return baseRepository.findAll(spec);
	}
	
	@Override
	public List<T> findThisAll(Map<String, Object> searchParams) {
		Map<String, SearchFilter> filters = SearchFilter.parse(searchParams);
		Specification<T> spec = DynamicSpecifications.bySearchFilter(filters.values(), entityClass);
		
		return baseRepository.findAll(spec);
	}
	
	@Transactional(readOnly = true)
	public T get(ID id) {
		T entity = baseRepository.findOne(id);
		if (entity == null) {
			throw new RuntimeException(String.format("找不到id=%s的对象", id));
		}
		return entity;
	}

	@Transactional(readOnly = true)
	public T load(ID id) {
		return baseRepository.getOne(id);
	}
	
	@Transactional
	public T save(T entity) {
		if(entity.getCreatedBy() == null) {
			//TODO set spring security user
		}
		if(entity.getCreatedDate() == null) {
			entity.setCreatedDate(new Date());
		}
		return baseRepository.save(entity);
	}

	@Transactional
	public T update(T entity) {
		if(entity.getLastModifiedBy() == null) {
			//TODO set spring security user
		}
		if(entity.getLastModifiedDate() == null) {
			entity.setLastModifiedDate(new Date());
		}
		return baseRepository.save(entity);
	}
	
	@Transactional
	public void delete(T entity) {
		baseRepository.delete(entity);		
	}

	@Transactional
	public void delete(ID id) {
		baseRepository.delete(id);			
	}

	@Transactional
	public void delete(ID[] ids) {
		for (int i = 0; i < ids.length; i++) {
			ID id = ids[i];
			delete(id);
		}
		
	}
	@Override
	public void deleteAll() {
		baseRepository.deleteAll();
	}
	
	
 @Transactional
public void batchInsert(List list) {
    for (int i = 0; i < list.size(); i++) {
        em.persist(list.get(i));
        if (i % 30 == 0) {
            em.flush();
            em.clear();
        }
    }
}
 
@Transactional
public void batchUpdate(List list) {
    for (int i = 0; i < list.size(); i++) {
        em.merge(list.get(i));
        if (i % 30 == 0) {
            em.flush();
            em.clear();
        }
    }
}


}
